import socket

from pydantic import Field, BaseModel
from pydantic_settings import BaseSettings, SettingsConfigDict

from config.app_config import AppConfig
from core.config import Config
from core.logger import Logger


class NacosServiceData(BaseModel):
    name: str = Field(description='服务名称')
    ip: str = Field(description='服务IP')
    port: int = Field(description='服务端口')


class NacosConfigData(BaseModel):
    data_id: str = Field(description='配置ID')
    group: str = Field(description='配置组')


_app_config = Config.get(AppConfig)


class NacosConfig(BaseSettings):
    model_config = SettingsConfigDict(env_file='.env', env_file_encoding='utf-8', extra='ignore')
    enable: bool = Field(description='是否启用Nacos', alias='USE_NACOS', default=False)
    nacos_ip: str = Field(description='Nacos服务器IP', alias='NACOS_IP', default='47.106.102.66')
    nacos_port: int = Field(description='Nacos服务器端口', alias='NACOS_PORT', default=8848)
    namespace: str = Field(description='Nacos命名空间', alias='ENV', default='dev')
    group: str = Field(description='Nacos组', alias='NACOS_GROUP', default='XLAB')
    username: str = Field(description='Nacos用户名', alias='NACOS_USERNAME', default='')
    password: str = Field(description='Nacos密码', alias='NACOS_PASSWORD', default='')
    service_ip: str = Field(description='服务IP', alias='IP', default='')
    enable_listen: bool = Field(description='是否监听Nacos配置', alias='NACOS_ENABLE_LISTEN', default=False)

    def get_service_data(self) -> list[NacosServiceData]:
        ip = self.service_ip or self._get_ip()
        return [NacosServiceData(name=_app_config.app_name, ip=ip, port=_app_config.port)]

    def get_config_data(self) -> NacosConfigData:
        return NacosConfigData(
            data_id=f'{_app_config.app_name}-{_app_config.app_env.value}.yml',
            group=self.group,
        )

    def get_server_address(self):
        return f'{self.nacos_ip}:{self.nacos_port}'

    @classmethod
    def _get_ip(cls) -> str:
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            s.connect(('8.8.8.8', 80))
            ip = s.getsockname()[0]
            s.close()
            return ip
        except Exception as e:
            Logger.get().error(f'获取IP失败: {e}')
            return '127.0.0.1'
